#include "editor_view.h"

EditorView::EditorView(std::shared_ptr<EditorScene> scene,QWidget *parent)
    :QGraphicsView(parent)
{
    // for unique_ptr
    // this->editorScene = std::move(scene);
    this->editorScene = scene;

    this->setScene(this->editorScene.get());
    this->setRenderHints(QPainter::Antialiasing | QPainter::HighQualityAntialiasing |
                         QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform);
    this->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);  // 防止画线的bug？
    this->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    this->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);

    this->setTransformationAnchor(QGraphicsView::AnchorUnderMouse); //设置锚点
    this->setDragMode(QGraphicsView::RubberBandDrag);  // 框选

    this->input_node_index = -1;
    this->input_socket_index = -1;
    this->output_node_index = -1;
    this->output_socket_index = -1;

}
EditorView::~EditorView()
{
    this->editorScene.reset();
    this->edge.reset();
    this->edge_temp.reset();
//    this->obj.reset();
//    this->item.reset();
    this->nodes.clear();
    this->edges.clear();
    QVector<std::shared_ptr<NodeEnsemble>>().swap(nodes);
    QVector<std::shared_ptr<NodeEdge>>().swap(edges);
}
void EditorView::keyPressEvent(QKeyEvent *event){
    if((event->modifiers()== Qt::ShiftModifier) && event->key() == Qt::Key_A){
        this->addNode(number++);
        return;
    }
    QGraphicsView::keyPressEvent(event);
}

void EditorView::mousePressEvent(QMouseEvent *event){
    if(event->button()== Qt::MiddleButton){
        this->middleMouseButtonPress(event);
    }
    else if(event->button() == Qt::LeftButton){
        leftMouseButtonPress(event);
    }
    else if(event->button() == Qt::RightButton){
        RightMouseButtonPress(event);
    }
    else{
        QGraphicsView::mousePressEvent(event);
    }
}

void EditorView::mouseReleaseEvent(QMouseEvent *event){
    if(event->button()== Qt::MiddleButton){
        this->middleMouseButtonRelease(event);
    }
    else if(event->button() == Qt::LeftButton){
        LeftMouseButtonRelease(event);
    }
    else if(event->button() == Qt::RightButton){
        RightMouseButtonRelease(event);
    }
    else{
        QGraphicsView::mouseReleaseEvent(event);
    }
}
void EditorView::mouseMoveEvent(QMouseEvent *event)
{
    if(is_edge_temp_alive){
        QPointF pos = mapToScene(event->pos());

        this->edge_temp->setEndPos(pos);
        this->editorScene->update();
    }
    QGraphicsView::mouseMoveEvent(event);
}
void EditorView::middleMouseButtonPress(QMouseEvent *event){
    QMouseEvent *releaseEvent =new QMouseEvent(QEvent::MouseButtonPress, event->localPos(),
                                           event->screenPos(), Qt::LeftButton, Qt::NoButton, event->modifiers());
    QGraphicsView::mouseReleaseEvent(releaseEvent);
    this->setDragMode(QGraphicsView::ScrollHandDrag);  // 设置鼠标形状
    QMouseEvent *fakeEvent = new QMouseEvent(event->type(),event->localPos(),event->screenPos(),
                                             Qt::LeftButton, event->buttons() | Qt::LeftButton ,event->modifiers());
    QGraphicsView::mouseReleaseEvent(fakeEvent);

    delete releaseEvent;
    delete fakeEvent;
}

void EditorView::middleMouseButtonRelease(QMouseEvent *event){
    QMouseEvent *fakeEvent = new QMouseEvent(event->type(),event->localPos(),event->screenPos(),
                                             Qt::LeftButton, event->buttons() | Qt::LeftButton ,event->modifiers());
    QGraphicsView::mouseReleaseEvent(fakeEvent);
    this->setDragMode(QGraphicsView::RubberBandDrag);

    delete fakeEvent;
}
void EditorView::leftMouseButtonPress(QMouseEvent *event)
{
    QGraphicsView::mousePressEvent(event);
    QPoint pos = event->pos();
    QPointF obj_pos = mapToScene(pos);

// TODO:使用智能指针的话，obj和edge_temp会在函数结束后释放一个计数吗？
    for(int i=0;i<this->nodes.length();i++){
        if(this->nodes[i]->item->contains(obj_pos)){
            // qDebug()<<"Click: Node:"<<this->nodes[i]->index;
            this->output_node_index = this->nodes[i]->index;

            // 如果选中了output socket，则产生虚拟连线
            for(int j=0;j<this->nodes[i]->output_number;j++){
                if(this->nodes[i]->output[j]->contains(obj_pos)){
                    qDebug()<<"Click: OutSocket:"<<this->nodes[i]->index<<">"<<this->nodes[i]->output[j]->index;
                    this->edge_temp = std::make_shared<NodeEdgeTemp>(obj_pos,obj_pos);
                    this->editorScene->addItem(edge_temp.get());
                    is_edge_temp_alive = true;

                    this->output_socket_index = this->nodes[i]->output[j]->index;
                    return;
                }
            }
        }
    }



}

//TODO 增加连线模式以无需任何release都计算是否连线
void EditorView::LeftMouseButtonRelease(QMouseEvent *event)
{
    QGraphicsView::mouseReleaseEvent(event);
    if(is_edge_temp_alive){
        this->edge_temp->hide();
        this->editorScene->removeItem(this->edge_temp.get());
        //qDebug()<<this->editorScene->items().count();
        //this->scene()->views().count();
        is_edge_temp_alive = false;
    }


    QPoint pos = event->pos();
    QPointF obj_pos = mapToScene(pos);

    for(int i=0;i<this->nodes.length();i++){
        if(this->nodes[i]->item->contains(obj_pos)){
            this->input_node_index = this->nodes[i]->index;

            // 如果选中了input socket，则产生连线
            for(int j=0;j<this->nodes[i]->input_number;j++){
                if(this->nodes[i]->input[j]->contains(obj_pos)){

                    // 不允许自己连自己
                    if(this->nodes[i]->index == this->output_node_index){
                        qDebug()<<"Warning: you can not connect node to itself";
                        return;
                    }
                    // 不允许非法连接
                    if(output_node_index==-1 || output_socket_index==-1 || input_node_index==-1)
                        return;
                    qDebug()<<"Connect: InSocket:"<<this->nodes[i]->index<<">"<<this->nodes[i]->input[j]->index;

                    this->input_socket_index = this->nodes[i]->input[j]->index;
                    addEdge(output_node_index,output_socket_index,input_node_index,input_socket_index);

                    return;
                }
            }
        }
    }



}
void EditorView::RightMouseButtonPress(QMouseEvent *event)
{
    QGraphicsView::mousePressEvent(event);
}
void EditorView::RightMouseButtonRelease(QMouseEvent *event)
{
    QGraphicsView::mouseReleaseEvent(event);
}

void EditorView::addNode(const int index)
{
    std::shared_ptr<NodeEnsemble> node_ensemble = std::make_shared<NodeEnsemble>(index);
    node_ensemble->setIndex(index);
    for(int i=0;i<node_ensemble->output.length();i++){
        node_ensemble->output[i]->node_index = node_ensemble->index;
    }
    for(int i=0;i<node_ensemble->input.length();i++){
        node_ensemble->input[i]->node_index = index;
        //node_ensemble->input[i]->out_socket_index = -1;
        //nodeScene->input[i]->isConnected = false;
    }
    nodes.push_back(node_ensemble);

    this->editorScene->addItem(nodes[nodes.length()-1]->item.get());
}

void EditorView::addNode(const int index, const int type)
{
    qDebug()<<index<<type;
}

void EditorView::addEdge(int start_node_index, int start_socket_index, int end_node_index, int end_socket_index)
{
    if(start_node_index==-1 || start_socket_index==-1 || end_node_index==-1 || end_socket_index==-1)
        return;
    std::shared_ptr<NodeEnsemble> sn;
    std::shared_ptr<NodeEnsemble> en;
    std::shared_ptr<NodeSocket> ss;
    std::shared_ptr<NodeSocket> es;
    for(int i=0;i<this->nodes.length();i++){

        if(this->nodes[i]->index == start_node_index){
            sn = this->nodes[i];
            for(int j=0;j<this->nodes[i]->output_number;j++){
                if(this->nodes[i]->output[j]->index == start_socket_index){
                    ss = this->nodes[i]->output[j];
                    break;
                }
            }
        }
        if(this->nodes[i]->index == end_node_index){
            en = this->nodes[i];
            for(int j=0;j<this->nodes[i]->input_number;j++){
                if(this->nodes[i]->input[j]->index == end_socket_index){
                    es = this->nodes[i]->input[j];
                    break;
                }
            }
        }
    }
    qDebug()<<sn->index<<en->index<<ss->index<<es->index;
    this->edge = std::make_shared<NodeEdge>(sn,en,ss,es);
    this->edge->setZValue(-1);
    edges.append(this->edge);
    this->editorScene->addItem(this->edge.get());
}

std::shared_ptr<QGraphicsItem> EditorView::NodeToItem(std::shared_ptr<NodeEnsemble> node)
{
    std::shared_ptr<QGraphicsItem> item(node->item);
    return item;
}

std::shared_ptr<QGraphicsItem> EditorView::EdgeToItem(std::shared_ptr<NodeEdge> edge)
{
    std::shared_ptr<QGraphicsItem> item(edge);
    return item;
}
void EditorView::wheelEvent(QWheelEvent *event)
{
    // the factor of zoom
    float zoomOutFactor = 1 / this->zoomInFactor;
    float zoomFactor;
    // store the scene pos
    QPointF *oldPos = new QPointF(this->mapToScene(event->pos()));
    Q_UNUSED(oldPos);
    if(event->angleDelta().y() > 0){
        zoomFactor = zoomInFactor;
        zoom += zoomStep;
    }
    else{
        zoomFactor = zoomOutFactor;
        zoom -= zoomStep;
    }

    BOOLEAN clamped = false;  // 放缩的限制
    if(this->zoom < zoomRange[0]){
        this->zoom = zoomRange[0];
        clamped = true;
    }
    if(this->zoom > zoomRange[1]){
        this->zoom = zoomRange[1];
        clamped = true;
    }

    if(!clamped || !this->zoomClamp)
        this->scale(zoomFactor,zoomFactor);  // set scene scale

    //TODO 清晰化
    /*
    QPointF *newPos = new QPointF(this->mapToScene(event->pos()));
    QPointF *delta = new QPointF(*newPos - *oldPos);
    this->translate(delta->x(),delta->y());
    this->translate(100.0,100.0);
    */


   // event->accept();
}
